package cn.etg.core;

import cn.etg.annotation.Controller;
import cn.etg.annotation.RequestMapping;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class HandlerMapping {
    private static Map<String, Method> mapping= new HashMap<>();
    static {
        initMapping();
    }

    public static  void initMapping(){
/*
         我们获得本次请求的路径uriPath值后，我们先判断是否为业务：
         1.扫描controler包下的所有类
         2.查看哪些被注解@Controller标注过的类(只有被该注解标注的类
         才是业务处理类)
         3.遍历这些类，并获取所有的方法，并查看哪些是业务方法只有
         被注解@RequestMapping标注的方法才是业务方法。
         4.遍历业务方法时对比该方法上@RequestMapping中传递的参数值是否与
         本次请求路径一致？如果一致说明本次请求就应当由该方法处理。
         因此利用反射机制调用该方法进行处理。
         提示：反射调用后要记得return，避免执行后续处理静态资源的操作
         5.如果扫描了所有的Controller中所有业务方法，均未找到与本次
         匹配的路径则说明本次请求并非业务处理业务，那么执行下面请求静态资源
         的操作，对于包而言，我们只扫描cn.etg.controller包

         */
        try {
            File baseDir = new File( HandlerMapping.class.getClassLoader().getResource(".").toURI());
            //获得controller包
            File controller = new File(baseDir,"cn/etg/controller");
            // 获得controller包下的.class文件
            File[] files = controller.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".class");
                }
            });
            // 遍历所有的.class文件
            for (File sub:files){
                // 获得文件名的前缀
                String className= sub.getName().substring(0,sub.getName().indexOf("."));
                // 获得类对象
                Class cls = Class.forName("cn.etg.controller."+className);
                // 判断该类是否被注解Controller
                if(cls.isAnnotationPresent(Controller.class)){
                    // 获得controller类中的所有方法
                    Method[] methods = cls.getDeclaredMethods();
                    // 遍历素有方法
                    for (Method method:methods){
                        // 判断方法上是否被注解RequestMapping
                        if(method.isAnnotationPresent(RequestMapping.class)){
                            // 获取注解参数
                            RequestMapping rm = method.getAnnotation(RequestMapping.class);
                            String value = rm.value();
//                            // 判断本次请求路径是否与该方法上@RequestMapping注解参数值一致
//                            if(value.equals(uriPath)){
//                                // 反射实例化Controller，且调用方法
//                                Object o = cls.newInstance();
//                                method.invoke(o,request,response);
//                                return;
//                            }
                            mapping.put(value,method);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据请求路径获取对应的处理方法
     * @param path
     * @return
     */
    public static Method getMethod(String path){
        return mapping.get(path);
    }

}
